/*
 *  Copyright (C) 2017 OrionStar Technology Project
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.abc.robot01

import android.app.Application
import android.content.Context
import android.os.HandlerThread
import android.util.Log
import com.abc.robot01.activity.showToast
import com.abc.robot01.retrofit.RetrofitService
import com.abc.robot01.vivemodel.Robot
import com.ainirobot.coreservice.client.ApiListener
import com.ainirobot.coreservice.client.RobotApi
import com.ainirobot.coreservice.client.module.ModuleCallbackApi
import com.ainirobot.coreservice.client.speech.SkillApi
import com.facebook.react.PackageList
import com.facebook.react.ReactApplication
import com.facebook.react.ReactHost
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.react.soloader.OpenSourceMergedSoMapping
import com.facebook.soloader.SoLoader
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class RobotOSApplication : Application(), ReactApplication {

    override val reactNativeHost: ReactNativeHost =
        object : DefaultReactNativeHost(this) {
            override fun getPackages(): List<ReactPackage> =
                PackageList(this).packages.apply {
                    // Packages that cannot be autolinked yet can be added manually here, for example:
                    // add(MyReactNativePackage())
                    add(NativeLocalStoragePackage())
                }

            override fun getJSMainModuleName(): String = "index"

            override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG

            override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
            override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
        }

    override val reactHost: ReactHost
        get() = getDefaultReactHost(applicationContext, reactNativeHost)


    private var mContext: Context? = null
    private var mSkillApi: SkillApi? = null

    private var mSkillCallback: SpeechCallback? = null
    private var mApiCallbackThread: HandlerThread? = null
    private var mModuleCallback: ModuleCallbackApi? = null
    override fun onCreate() {
        super.onCreate()
        mContext = this
//        instance = this
        if (ROBOT) {
            init()
            initRobotApi()
        }
        SoLoader.init(this, OpenSourceMergedSoMapping)
        if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
            // If you opted-in for the New Architecture, we load the native entry point for this app.
            load()
        }
        RobotOSApplication.ins = this
    }

    private fun init() {
        mSkillCallback = SpeechCallback()
        mModuleCallback = ModuleCallback()
        mApiCallbackThread = HandlerThread("RobotOSDemo")
        mApiCallbackThread!!.start()
    }

    private fun initRobotApi() {
        RobotApi.getInstance().connectServer(mContext, object : ApiListener {
            override fun handleApiDisabled() {
                Log.i(TAG, "handleApiDisabled")
            }

            /**
             * Server connected, set callback to handle message
             * Server已连接，设置接收请求的回调，包含语音指令、系统事件等
             *
             * Start connect RobotOS, init and make it ready to use
             * 启动与RobotOS连接，这里可以做一些初始化的工作 例如连接语音,本地服务等
             */
            override fun handleApiConnected() {
                Log.i(TAG, "handleApiConnected")
                addApiCallBack()
                initSkillApi()
            }

            /**
             * Disconnect RobotOS
             * 连接已断开
             */
            override fun handleApiDisconnected() {
                Log.i(TAG, "handleApiDisconnected")
            }
        })
    }

    private fun addApiCallBack() {
        Log.d(TAG, "CoreService connected ")
        RobotApi.getInstance().setCallback(mModuleCallback)
        RobotApi.getInstance().setResponseThread(mApiCallbackThread)
    }

    private fun initSkillApi() {
        mSkillApi = SkillApi()
        val apiListener: ApiListener = object : ApiListener {
            override fun handleApiDisabled() {
            }

            /**
             * Handle speech service
             * 语音服务连接成功，注册语音回调
             */
            override fun handleApiConnected() {
                mSkillApi!!.registerCallBack(mSkillCallback)
            }

            /**
             * Disconnect speech service
             * 语音服务已断开
             */
            override fun handleApiDisconnected() {
            }
        }
        mSkillApi!!.addApiEventListener(apiListener)
        mSkillApi!!.connectApi(mContext)
    }

    val skillApi: SkillApi?
        get() {
            if (mSkillApi!!.isApiConnectedService) {
                return mSkillApi
            }
            return null
        }


    fun registerCallBack(skillCallback: AsrCallback) {
        mSkillCallback!!.skillCallback = skillCallback
    }

    fun unregisterCallBack() {
        mSkillCallback!!.skillCallback = null
    }

    companion object {
        private val TAG: String = RobotOSApplication::class.java.name
        var ROBOT: Boolean = true
//        var ROBOT: Boolean = false
//        var instance: RobotOSApplication? = null
//            private set

        private lateinit var ins: RobotOSApplication
        fun  getInstance():RobotOSApplication  {
            return ins
        }
    }
}


